package org.ruoyi.aibox.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
import org.ruoyi.common.core.exception.ServiceException;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Word文档处理器
 */
@Slf4j
@Service
public class DocumentProcessor {
    
    // 数字标题模式，匹配如：1、1.、1.1、1.1.1等格式
    private static final Pattern NUMBER_HEADING_PATTERN = Pattern.compile("^\\d+(\\.\\d+)*[.、]?\\s*.+");
    
    // 中文标题模式，匹配如：一、(一)等格式
    private static final Pattern CHINESE_HEADING_PATTERN = Pattern.compile("^[一二三四五六七八九十百千万]+[、.]\\s*.+|^[（(][一二三四五六七八九十百千万]+[)）]\\s*.+");
    
    /**
     * 处理Word文档，提取章节内容
     *
     * @param filePath 文档路径
     * @return 章节内容映射表，key为章节标题，value为章节内容
     */
    public Map<String, String> processDocument(String filePath) {
        Map<String, String> chapterMap = new HashMap<>();
        
        try (XWPFDocument document = new XWPFDocument(new FileInputStream(filePath))) {
            StringBuilder currentChapter = new StringBuilder();
            String currentTitle = null;
            
            // 遍历所有段落
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                // 检查是否是标题
                if (isHeading(paragraph)) {
                    // 如果已有章节内容，保存之前的章节
                    if (currentTitle != null && currentChapter.length() > 0) {
                        chapterMap.put(currentTitle, currentChapter.toString().trim());
                        currentChapter = new StringBuilder();
                    }
                    // 更新当前标题
                    currentTitle = paragraph.getText().trim();
                    log.debug("找到章节标题: {}", currentTitle);
                } else if (currentTitle != null) {
                    // 添加到当前章节内容，保留段落格式
                    String paragraphText = getParagraphText(paragraph);
                    if (!paragraphText.isEmpty()) {
                        currentChapter.append(paragraphText).append("\n");
                    }
                } else {
                    // 未找到标题的内容放入"前言"
                    if (!chapterMap.containsKey("前言")) {
                        chapterMap.put("前言", "");
                    }
                    String paragraphText = getParagraphText(paragraph);
                    if (!paragraphText.isEmpty()) {
                        chapterMap.put("前言", chapterMap.get("前言") + paragraphText + "\n");
                    }
                }
            }
            
            // 保存最后一个章节
            if (currentTitle != null && currentChapter.length() > 0) {
                chapterMap.put(currentTitle, currentChapter.toString().trim());
            }
            
            // 保存全文
            StringBuilder fullText = new StringBuilder();
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                String paragraphText = getParagraphText(paragraph);
                if (!paragraphText.isEmpty()) {
                    fullText.append(paragraphText).append("\n");
                }
            }
            chapterMap.put("全文", fullText.toString().trim());
            
            log.info("文档处理完成，共提取{}个章节", chapterMap.size() - 1); // 减去"全文"
            
        } catch (Exception e) {
            log.error("处理Word文档失败: {}", filePath, e);
            // 使用备用方案：读取为纯文本
            try {
                String plainText = new String(Files.readAllBytes(Paths.get(filePath)));
                chapterMap.put("全文", plainText);
                log.warn("使用备用方案：将文档作为纯文本处理");
            } catch (Exception ex) {
                log.error("读取文件失败: {}", filePath, ex);
                throw new ServiceException("文档处理失败：" + e.getMessage());
            }
        }
        
        return chapterMap;
    }
    
    /**
     * 判断段落是否为标题
     */
    private boolean isHeading(XWPFParagraph paragraph) {
        try {
            String text = paragraph.getText().trim();
            if (text.isEmpty()) {
                return false;
            }

            // 1. 检查样式名称
            String style = paragraph.getStyle();
            if (style != null) {
                style = style.toLowerCase();
                if (style.contains("heading") || style.contains("标题") || style.contains("title")) {
                    return true;
                }
            }

            // 2. 检查自定义样式
            XWPFStyle paragraphStyle = paragraph.getDocument().getStyles().getStyle(paragraph.getStyleID());
            if (paragraphStyle != null) {
                CTString styleName = paragraphStyle.getCTStyle().getName();
                if (styleName != null && styleName.getVal() != null) {
                    String customStyle = styleName.getVal().toLowerCase();
                    if (customStyle.contains("heading") || customStyle.contains("标题") || customStyle.contains("title")) {
                        return true;
                    }
                }
            }
            
            // 3. 检查大纲级别
            if (paragraph.getCTP().getPPr() != null && 
                paragraph.getCTP().getPPr().getOutlineLvl() != null) {
                return true;
            }

            // 4. 检查字体大小和加粗
            XWPFRun run = paragraph.getRuns().isEmpty() ? null : paragraph.getRuns().get(0);
            if (run != null) {
                // 检查字体大小（默认字号为11或12）
                int fontSize = run.getFontSize();
                boolean isBold = run.isBold();
                if ((fontSize == -1 && isBold) || fontSize > 12) {
                    return true;
                }
            }

            // 5. 检查数字标题格式
            if (NUMBER_HEADING_PATTERN.matcher(text).matches()) {
                return true;
            }

            // 6. 检查中文标题格式
            return CHINESE_HEADING_PATTERN.matcher(text).matches();

        } catch (Exception e) {
            log.warn("检查段落样式失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 获取段落文本，保留基本格式
     */
    private String getParagraphText(XWPFParagraph paragraph) {
        StringBuilder text = new StringBuilder();
        
        // 获取段落缩进
        String indent = "";
        if (paragraph.getIndentationLeft() > 0) {
            indent = " ".repeat((int)(paragraph.getIndentationLeft() / 240)); // 240 twips = 1 character width
        }
        
        // 处理段落内容
        if (!paragraph.getRuns().isEmpty()) {
            text.append(indent);
            for (XWPFRun run : paragraph.getRuns()) {
                String runText = run.getText(0);
                if (runText != null) {
                    text.append(runText);
                }
            }
        }
        
        return text.toString().trim();
    }
} 